package org.example.exampreparationtreasure.controller;

import org.example.exampreparationtreasure.common.ApiResponse;
import org.example.exampreparationtreasure.mapper.*;
import org.example.exampreparationtreasure.model.dto.DateRange;
import org.example.exampreparationtreasure.model.entity.*;
import org.example.exampreparationtreasure.util.CsvUtils;
import org.example.exampreparationtreasure.service.KnowledgeMasteryService;
import org.example.exampreparationtreasure.service.LearningAnalysisService;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.example.exampreparationtreasure.model.vo.*;
import org.example.exampreparationtreasure.util.JwtUtil;
import org.example.exampreparationtreasure.config.JwtConfig;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学习分析控制器
 * 提供学习数据分析相关的API接口，包括学习概览、知识掌握度、薄弱点分析等功能
 */

@RestController
@RequestMapping("/api/v1/learning")
@RequiredArgsConstructor
public class LearningAnalysisController {
	private final LearningAnalysisService learningAnalysisService;
	private final KnowledgeMasteryService knowledgeMasteryService;
	private final JwtUtil jwtUtil;
	private final JwtConfig jwtConfig;

	//添加Mapper依赖
	private final ExamRecordMapper examRecordMapper;
	private final IncorrectQuestionRecordMapper incorrectMapper;
	private final QuestionCategoryMapper categoryMapper;
	private final UserMapper userMapper;
	private final AnswerMapper answerMapper;

	/**
	 * 获取学习概览
	 * 分析用户的学习状态，包括答题总数、正确率、平均分等关键指标
	 *
	 *
	 * @return 学习概览数据，包含答题统计和准确率信息
	 */
	@GetMapping("/overview")
	public ApiResponse<LearningOverview> getLearningOverview(HttpServletRequest request) {
		try {
			System.out.println("=== 开始处理学习概览请求 ===");

			String token = request.getHeader(jwtConfig.getHeader());
			Long userId;
			if (token != null && !token.trim().isEmpty()) {
				try {
					userId = jwtUtil.getUserIdByToken(token);
				} catch (Exception e) {
					userId = 1969704081851781122L;
				}
			} else {
				userId = 1969704081851781122L;
			}

			// 使用ExamRecord替代LearningStatus
			List<ExamRecord> examRecords = getExamRecordsByUserId(userId);

			// 构建返回的学习概览对象
			LearningOverview vo = new LearningOverview();
			vo.setUserId(userId);

			// 从ExamRecord计算统计数据，添加了null值检查
			int totalAnswered = examRecords.stream()
					.filter(er -> er.getTotalQuestions() != null)  // 添加这一行
					.mapToInt(ExamRecord::getTotalQuestions)
					.sum();
			vo.setTotalAnswered(totalAnswered);

			//添加了null值检查
			int correctCount = examRecords.stream()
					.filter(er -> er.getCorrectAnswers() != null)  // 添加这一行
					.mapToInt(ExamRecord::getCorrectAnswers)
					.sum();
			vo.setCorrectCount(correctCount);

			double accuracy = totalAnswered > 0 ? (double) correctCount / totalAnswered : 0.0;
			vo.setAccuracy(accuracy);

			double avgScore = examRecords.stream()
					.filter(er -> er.getTotalScore() != null)
					.mapToDouble(er -> er.getTotalScore().doubleValue())
					.average()
					.orElse(0.0);
			vo.setAvgScore(avgScore);

			return ApiResponse.ok(vo);

		} catch (Exception e) {
			System.err.println("=== 学习概览请求处理异常 ===");
			e.printStackTrace();
			return ApiResponse.error("服务器内部错误: " + e.getMessage());
		}
	}

	/**
	 * 获取知识掌握度
	 * 分析用户在各个知识分类上的掌握程度，用于个性化学习推荐
	 *
	 *
	 * @return 知识掌握度映射，key为分类ID，value为掌握度(0-1)
	 */
	@GetMapping("/mastery")
	public ApiResponse<KnowledgeMastery> getKnowledgeMastery(HttpServletRequest request) {
		try {
			System.out.println("=== 开始处理知识掌握度请求 ===");
			
			String token = request.getHeader(jwtConfig.getHeader());
			System.out.println("获取到的token: " + (token != null ? "存在" : "不存在"));
			
			Long userId = jwtUtil.getUserIdByToken(token);
			System.out.println("从token解析出的userId: " + userId);
			
			KnowledgeMastery km = new KnowledgeMastery();
			km.setUserId(userId);
			
			System.out.println("调用知识掌握度服务");
			Map<Long, Double> masteryMap = knowledgeMasteryService.getMasteryMap(userId);
			System.out.println("知识掌握度服务返回结果: " + masteryMap);
			
			km.setMasteryMap(masteryMap);
			
			System.out.println("构建的知识掌握度对象: " + km);
			System.out.println("=== 知识掌握度请求处理完成 ===");
			
			return ApiResponse.ok(km);
			
		} catch (Exception e) {
			System.err.println("=== 知识掌握度请求处理异常 ===");
			System.err.println("异常类型: " + e.getClass().getSimpleName());
			System.err.println("异常消息: " + e.getMessage());
			System.err.println("异常堆栈: ");
			e.printStackTrace();
			return ApiResponse.error("服务器内部错误: " + e.getMessage());
		}
	}

	/**
	 * 获取薄弱点分析
	 * 识别用户学习中的薄弱环节，帮助制定针对性学习计划
	 *
	 *
	 * @return 薄弱点分析结果，包含薄弱分类ID和错误次数统计
	 */
	@GetMapping("/weakness")
	public ApiResponse<WeaknessAnalysis> getWeaknessAnalysis(HttpServletRequest request) {
		String token = request.getHeader(jwtConfig.getHeader());
		Long userId = jwtUtil.getUserIdByToken(token);

		// 使用IncorrectQuestionRecord替代WeaknessDiagnosis
		List<IncorrectQuestionRecord> incorrectRecords = getIncorrectRecordsByUserId(userId);

		WeaknessAnalysis wa = new WeaknessAnalysis();
		wa.setUserId(userId);

		// 从IncorrectQuestionRecord提取薄弱分类ID
		List<Long> weakCategoryIds = incorrectRecords.stream()
				.map(IncorrectQuestionRecord::getCategoryId)
				.distinct()
				.collect(Collectors.toList());
		wa.setWeakCategoryIds(weakCategoryIds);

		// 构建错误次数统计映射
		Map<Long, Integer> mistakeCounts = new HashMap<>();
		for (IncorrectQuestionRecord record : incorrectRecords) {
			Long categoryId = record.getCategoryId();
			mistakeCounts.merge(categoryId, record.getMistakeCount(), Integer::sum);
		}
		wa.setMistakeCounts(mistakeCounts);

		return ApiResponse.ok(wa);
	}
	/**
	 * 获取学习进度
	 * 展示用户的学习活跃度和进度情况
	 *
	 *
	 * @return 学习进度信息，包含活跃天数、学习会话数等
	 */
	@GetMapping("/progress")
	public ApiResponse<LearningProgress> getLearningProgress(HttpServletRequest request) {
		String token = request.getHeader(jwtConfig.getHeader());
		Long userId = jwtUtil.getUserIdByToken(token);
		LearningProgress lp = new LearningProgress();
		lp.setUserId(userId);
		// 从数据库获取活跃天数（有考试记录的不同日期数）
		LambdaQueryWrapper<ExamRecord> dateQuery = new LambdaQueryWrapper<>();
		dateQuery.eq(ExamRecord::getUserId, userId)
				.select(ExamRecord::getStartTime);
		List<ExamRecord> examRecords = examRecordMapper.selectList(dateQuery);

		long daysActive = examRecords.stream()
				.map(er -> er.getStartTime().toLocalDate())
				.distinct()
				.count();
		lp.setDaysActive((int) daysActive);

		// 从数据库获取学习会话数（考试记录数）
		lp.setSessions(examRecords.size());

		// 获取最后活跃时间
		LocalDateTime lastActiveTime = examRecords.stream()
				.map(ExamRecord::getStartTime)
				.max(LocalDateTime::compareTo)
				.orElse(LocalDateTime.now());
		lp.setLastActiveTime(lastActiveTime);

		return ApiResponse.ok(lp);
	}

	/**
	 * 获取用户活动
	 * 统计用户的学习活动情况
	 *
	 *
	 * @return 用户活动统计，包含操作次数和答题数量
	 */
	@GetMapping("/activity")
	public ApiResponse<UserActivity> getUserActivity(HttpServletRequest request) {
		String token = request.getHeader(jwtConfig.getHeader());
		Long userId = jwtUtil.getUserIdByToken(token);
		UserActivity ua = new UserActivity();
		ua.setUserId(userId);
		// 从数据库获取用户操作次数（考试记录数）
		LambdaQueryWrapper<ExamRecord> examQuery = new LambdaQueryWrapper<>();
		examQuery.eq(ExamRecord::getUserId, userId);
		long actions = examRecordMapper.selectCount(examQuery);
		ua.setActions((int) actions);

		// 从数据库获取答题数量（答题记录数）
		LambdaQueryWrapper<Answer> answerQuery = new LambdaQueryWrapper<>();
		answerQuery.eq(Answer::getUserId, userId);
		long answered = answerMapper.selectCount(answerQuery);
		ua.setAnswered((int) answered);

		return ApiResponse.ok(ua);
	}

	/**
	 * 导出分析报告
	 * 生成用户学习分析报告并导出为CSV文件
	 *
	 * @param request 导出请求，包含用户ID
	 * @param response HTTP响应对象，用于文件下载
	 * @throws Exception 文件生成异常
	 */
	@PostMapping("/reports/export")
	public void exportAnalysisReport(@RequestBody ReportExportRequest request, HttpServletRequest httpRequest, HttpServletResponse response) throws Exception {
		String token = httpRequest.getHeader(jwtConfig.getHeader());
		Long userId = jwtUtil.getUserIdByToken(token);

		// 使用User替代AnalysisReport
		User user = getUserById(userId);
		List<ExamRecord> examRecords = getExamRecordsByUserId(userId);

		// 定义CSV文件表头
		List<String> headers = Arrays.asList("userId", "username", "totalExams", "totalScore", "avgScore");

		// 构建CSV数据行
		// 构建CSV数据行 - 添加null检查
		String username = (user != null && user.getUsername() != null) ? user.getUsername() : "未知用户";

		double totalScore = examRecords.stream()
				.filter(er -> er.getTotalScore() != null) // 过滤掉total_score为null的记录
				.mapToDouble(er -> er.getTotalScore().doubleValue())
				.sum();

		double avgScore = examRecords.stream()
				.filter(er -> er.getTotalScore() != null) // 过滤掉total_score为null的记录
				.mapToDouble(er -> er.getTotalScore().doubleValue())
				.average()
				.orElse(0.0);

		List<List<String>> rows = Collections.singletonList(Arrays.asList(
				String.valueOf(userId),
				username,
				String.valueOf(examRecords.size()),
				String.valueOf(totalScore),
				String.valueOf(avgScore)
		));

		CsvUtils.writeCsv(response, "analysis_report_" + userId, headers, rows);
	}

	/**
	 * 获取趋势分析
	 * 分析用户学习效果的时间趋势变化
	 *
	 * @param range 时间范围，包含开始和结束时间
	 * @return 趋势分析结果，包含每日准确率变化
	 */
	@PostMapping("/trend")
	public ApiResponse<Map<String, Object>> getTrend(@RequestBody DateRange range, HttpServletRequest request) {
		String token = request.getHeader(jwtConfig.getHeader());
		Long userId = jwtUtil.getUserIdByToken(token);

		// 使用QuestionCategory替代TrendAnalysis
		List<QuestionCategory> categories = getAllQuestionCategories();

		Map<String, Object> trendData = new HashMap<>();
		trendData.put("userId", userId);
		trendData.put("dateRange", range);
		trendData.put("categories", categories);

		// 计算真实的每日准确率数据
		Map<String, Double> dailyAccuracy = calculateRealDailyAccuracy(userId, range);
		trendData.put("dailyAccuracy", dailyAccuracy);

		return ApiResponse.ok(trendData);
	}
	/**
	 * 计算真实的每日准确率
	 * @param userId 用户ID
	 * @param range 时间范围
	 * @return 每日准确率映射
	 */
	private Map<String, Double> calculateRealDailyAccuracy(Long userId, DateRange range) {
		Map<String, Double> dailyAccuracy = new HashMap<>();

		// 解析时间范围
		LocalDateTime start = range.getStart() != null ? range.getStart() : LocalDate.now().minusDays(30).atStartOfDay();
		LocalDateTime end = range.getEnd() != null ? range.getEnd() : LocalDateTime.now();

		// 查询用户在指定时间范围内的答题记录
		LambdaQueryWrapper<Answer> answerQuery = new LambdaQueryWrapper<>();
		answerQuery.eq(Answer::getUserId, userId)
				.between(Answer::getCreateTime, start, end);

		List<Answer> answers = answerMapper.selectList(answerQuery);

		// 按日期分组统计
		Map<LocalDate, List<Answer>> answersByDate = new HashMap<>();
		for (Answer answer : answers) {
			LocalDate date = answer.getCreateTime().toLocalDate();
			answersByDate.computeIfAbsent(date, k -> new ArrayList<>()).add(answer);
		}

		// 计算每日准确率
		for (Map.Entry<LocalDate, List<Answer>> entry : answersByDate.entrySet()) {
			LocalDate date = entry.getKey();
			List<Answer> dayAnswers = entry.getValue();

			if (!dayAnswers.isEmpty()) {
				// 计算当天的准确率
				long correctCount = dayAnswers.stream()
						.filter(answer -> answer.getIsCorrect() != null && answer.getIsCorrect() == 1)
						.count();

				double accuracy = (double) correctCount / dayAnswers.size();
				dailyAccuracy.put(date.toString(), accuracy);
			}
		}

		// 如果没有答题记录，返回空Map
		return dailyAccuracy;
	}

	// 辅助方法 - 需要注入相应的Mapper
	private List<ExamRecord> getExamRecordsByUserId(Long userId) {
		LambdaQueryWrapper<ExamRecord> query = new LambdaQueryWrapper<>();
		query.eq(ExamRecord::getUserId, userId);
		return examRecordMapper.selectList(query);
	}

	private List<IncorrectQuestionRecord> getIncorrectRecordsByUserId(Long userId) {
		LambdaQueryWrapper<IncorrectQuestionRecord> query = new LambdaQueryWrapper<>();
		query.eq(IncorrectQuestionRecord::getUserId, userId)
				.orderByDesc(IncorrectQuestionRecord::getMistakeCount);
		return incorrectMapper.selectList(query);
	}

	private List<QuestionCategory> getAllQuestionCategories() {
		LambdaQueryWrapper<QuestionCategory> query = new LambdaQueryWrapper<>();
		query.orderByAsc(QuestionCategory::getSortOrder);
		return categoryMapper.selectList(query);
	}

	private User getUserById(Long userId) {
		return userMapper.selectById(userId);
	}
} 